﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Iterator
{
    class Program
    {
        static void Main(string[] args)
        {
            //ConcreteAggregate a = new ConcreteAggregate();
            //a[0] = "Item A";
            //a[1] = "Item B";
            //a[2] = "Item C";
            //a[3] = "Item D";
            //ConcreteIterator i = new ConcreteIterator(a);
            //Console.WriteLine("Iterating over collection:");
            //object item = i.First();
            //while (item != null)
            //{
            //    Console.WriteLine(item);
            //    item = i.Next();
            //}

            Collection collection = new Collection();
            collection[0] = new Item("Item 0");
            collection[1] = new Item("Item 1");
            collection[2] = new Item("Item 2");
            collection[3] = new Item("Item 3");
            collection[4] = new Item("Item 4");
            collection[5] = new Item("Item 5");
            collection[6] = new Item("Item 6");
            collection[7] = new Item("Item 7");
            collection[8] = new Item("Item 8");

            //Iterator iterator = new Iterator(collection);
            Iterator iterator = collection.CreateIterator();
            // Skip every other item
            iterator.Step = 2;
            Console.WriteLine("Iterating over collection:");
            for (Item item = iterator.First(); !iterator.IsDone(); item = iterator.Next() )
            {
                Console.WriteLine(item.Name);
            }

            Console.Read();
        }
    }

    //abstract class Aggregate
    //{
    //    public abstract Iterator CreateIterator();
    //}

    //class ConcreteAggregate : Aggregate
    //{
    //    private ArrayList _items = new ArrayList();

    //    public override Iterator CreateIterator()
    //    {
    //        return new ConcreteIterator(this);
    //    }

    //    public int Count { get { return this._items.Count; } }

    //    public object this[int index]
    //    {
    //        get { return this._items[index]; }
    //        set {
    //            this._items.Insert(index,value);
    //        }
    //    }
    //}

    //abstract class Iterator
    //{
    //    public abstract object First();
    //    public abstract object Next();
    //    public abstract bool IsDone();
    //    public abstract object CurrentItem();
    //}

    //class ConcreteIterator : Iterator
    //{
    //    private ConcreteAggregate _aggregate;
    //    private int _current = 0;

    //    public ConcreteIterator(ConcreteAggregate aggregate)
    //    { this._aggregate = aggregate; }

    //    public override object First()
    //    {
    //        return this._aggregate[0];
    //    }

    //    public override object Next()
    //    {
    //        object ret = null;
    //        if (_current < this._aggregate.Count - 1)
    //        { 
    //            ret = this._aggregate[++_current];
    //        }
    //        return ret;
    //    }
    //    public override object CurrentItem()
    //    {
    //        return _aggregate[_current];
    //    }
    //    public override bool IsDone()
    //    {
    //        return _current >= _aggregate.Count;
    //    }
    //}

    class Item
    {
        public string Name { get; set; }
        public Item(string name)
        {
            this.Name = name;
        }
    }

    interface IAbstractCollection
    {
        Iterator CreateIterator();
    }

    class Collection : IAbstractCollection
    {
        private List<Item> _collection = new List<Item>();
        public Iterator CreateIterator()
        {
            return new Iterator(this);
        }

        public int Count
        {
            get { return this._collection.Count; }
        }

        public Item this[int index]
        {
            get { return this._collection[index]; }
            set 
            {
                this._collection.Add(value);
            }
        }
    }

    interface IAbstractIterator
    {
        Item First();
        Item Next();
        bool IsDone();
        Item CurrentItem();
    }

    class Iterator : IAbstractIterator
    {
        public Collection Collection { get; set; }
        private int _step = 1;
        private int _current = 0;

        public int Step
        {
            get { return this._step; }
            set { this._step = value; }
        }
        public Iterator(Collection collection)
        {
            this.Collection = collection;
        }

        public Item First()
        {
            return this.Collection[0];
        }

        public Item CurrentItem()
        {
            return this.Collection[this._current];
        }

        public bool IsDone()
        {
            return this._current >= this.Collection.Count;
        }

        public Item Next()
        {
            this._current += this._step;
            if (!IsDone())
            {
                return this.Collection[this._current];
            }
            else
            {
                return null;
            }
        }
    }
}
